﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Media;
using ConfApp.Models.Dto;

namespace ConfApp.Models
{
    public class ConfAppModel
    {
        public bool IsInitialized
        {
            get { return Version != null; }
        }
        public int? Version { get; set; }
        public Dictionary<int,Company> Companies { get; set; }
        public Dictionary<int, Day> Days { get; set; }
        public Dictionary<int, Room> Rooms { get; set; }
        public Dictionary<int, Session> Sessions { get; set; }
        public Dictionary<int, Slot> Slots { get; set; }
        public Dictionary<int, Speaker> Speakers { get; set; }
        public Dictionary<int, Track> Tracks { get; set; }

        public static ConfAppModel FromDto(ConfAppModelDto dtoModel)
        {
            var model = new ConfAppModel();
            if (dtoModel.Companies == null) return model;
            
            model.Version = dtoModel.Version;
            LoadCompanies(dtoModel,model);
            LoadDays(dtoModel,model);
            LoadRooms(dtoModel, model);
            LoadTracks(dtoModel,model);
            LoadSlots(dtoModel,model);
            LoadSpeakers(dtoModel,model);
            LoadSessions(dtoModel,model);
            MakeSessionSpeakerRelations(dtoModel,model);
            return model;
        }

        private static void LoadCompanies(ConfAppModelDto dtoModel, ConfAppModel model)
        {
            model.Companies = new Dictionary<int, Company>();
            model.Companies.Add(-1,new Company(){ID=-1,ShortTitle = ""});
            foreach (var companyDto in dtoModel.Companies)
            {
                model.Companies.Add(
                    companyDto.ID,
                    new Company{ID=companyDto.ID,ShortTitle = companyDto.ShortTitle});
            }
        }

        private static void LoadDays(ConfAppModelDto dtoModel, ConfAppModel model)
        {
            model.Days = new Dictionary<int, Day>();
            model.Days.Add(-1,new Day(){ID=-1,Date = DateTime.MaxValue,Index = -1});
            var index = 0;
            foreach (var dayDto in dtoModel.Days.OrderBy(d=>d.Date) )
            {
                model.Days.Add(
                    dayDto.ID,
                    new Day(){ ID = dayDto.ID, Date = dayDto.Date, Index = index});
                index++;
            }
        }

        private static void LoadRooms(ConfAppModelDto dtoModel, ConfAppModel model)
        {
            model.Rooms = new Dictionary<int, Room>();
            model.Rooms.Add(-1, new Room() { ID = -1, Code = ""});
            foreach (var roomDto in dtoModel.Rooms)
            {
                model.Rooms.Add(
                    roomDto.ID,
                    new Room(){ ID = roomDto.ID, Code = roomDto.Code });
            }
        }

        private static void LoadTracks(ConfAppModelDto dtoModel, ConfAppModel model)
        {
            model.Tracks = new Dictionary<int, Track>();
            model.Tracks.Add(-1,new Track(){ID=-1,Code = "",Title = "Sve sesije",Color = Color.FromArgb(0,255,255,255)});
            foreach (var trackDto in dtoModel.Tracks)
            {
                model.Tracks.Add(
                    trackDto.ID,
                    new Track()
                                     {
                                         ID = trackDto.ID, 
                                         Code = trackDto.Code,
                                         Title = trackDto.Title,
                                         Description = trackDto.Description,
                                         Color = GetColor(trackDto.Color)
                                     });
            }
        }

        private static Color GetColor(string sColor)
        {
            var s = sColor.Trim().TrimStart('#');

            // only 8 (with alpha channel) or 6 symbols are allowed
            //if (s.Length != 8 && s.Length != 6)
            //    throw new ArgumentException("Unknown string format!");

            int startParseIndex = 0;
            bool alphaChannelExists = s.Length == 8; // check if alpha canal exists            

            // read alpha channel value
            byte a = 255;
            if (alphaChannelExists)
            {
                a = System.Convert.ToByte(s.Substring(0, 2), 16);
                startParseIndex += 2;
            }

            // read r value
            byte r = System.Convert.ToByte(s.Substring(startParseIndex, 2), 16);
            startParseIndex += 2;
            // read g value
            byte g = System.Convert.ToByte(s.Substring(startParseIndex, 2), 16);
            startParseIndex += 2;
            // read b value
            byte b = System.Convert.ToByte(s.Substring(startParseIndex, 2), 16);
            var color = Color.FromArgb(a, r, g, b);
            return color;
        }

        private static void LoadSlots(ConfAppModelDto dtoModel, ConfAppModel model)
        {
            model.Slots = new Dictionary<int, Slot>();
            model.Slots.Add(-1, new Slot(){ ID = -1, Day = model.Days[-1]});
            foreach (var slotDto in dtoModel.Slots)
            {
                model.Slots.Add(
                    slotDto.ID,
                    new Slot()
                    {
                        ID = slotDto.ID,
                        Day = model.Days[slotDto.DayID],
                        Type = slotDto.Type,
                        StartHour = slotDto.StartHour,
                        StartMinute = slotDto.StartMinute,
                        FinishHour = slotDto.FinishHour,
                        FinishMinute = slotDto.FinishMinute
                    });
            }
        }

        private static void LoadSpeakers(ConfAppModelDto dtoModel, ConfAppModel model)
        {
            model.Speakers = new Dictionary<int, Speaker>();
            foreach (var speakerDto in dtoModel.Speakers)
            {
                model.Speakers.Add(
                    speakerDto.ID,
                    new Speaker()
                    {
                        ID = speakerDto.ID,
                        FirstName = speakerDto.FirstName,
                        LastName = speakerDto.LastName,
                        Company = model.Companies[speakerDto.CompanyID],
                        Bio = speakerDto.Bio,
                        PictureUrl = speakerDto.PictureUrl,
                        Sessions = new List<Session>(),
                    });
            }
        }

        private static void LoadSessions(ConfAppModelDto dtoModel, ConfAppModel model)
        {
            model.Sessions = new Dictionary<int, Session>();
            foreach (var sessionDto in dtoModel.Sessions)
            {
                model.Sessions.Add(
                    sessionDto.ID,
                    new Session()
                    {
                        ID = sessionDto.ID,
                        LanguageCode = sessionDto.LanguageCode,
                        Level = sessionDto.Level,
                        Title = sessionDto.Title,
                        Description = sessionDto.Description,
                        Room = model.Rooms[sessionDto.RoomID],
                        Slot = model.Slots[sessionDto.SlotID],
                        Track = model.Tracks[sessionDto.TrackID],
                        IsFavourite = false,
                        Speakers = new List<Speaker>()
                    });
            }
        }

        private static void MakeSessionSpeakerRelations(ConfAppModelDto dtoModel, ConfAppModel model)
        {
            foreach (var relation in dtoModel.SessionSpeakerRelations)
            {
                var session = model.Sessions[relation.SessionID];
                var speaker = model.Speakers[relation.SpeakerID];

                session.Speakers.Add(speaker);
                speaker.Sessions.Add(session);
            }
        }

    }
}
